package cn.felord.app.exception;

import cn.felord.app.data.Rest;
import cn.felord.app.data.RestBody;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;
import java.util.List;

/**
 * 统一异常处理
 *
 * @author Dax
 * @since 14 :38  2019-04-18
 */
@Slf4j
@RestControllerAdvice
public class ApiExceptionHandler {


    /**
     * Handle rest.
     *
     * @param request the request
     * @param e       the e
     * @return the rest
     */
    @ExceptionHandler(Exception.class)
    public Rest handle(HttpServletRequest request, Exception e) {
        String contentType = request.getHeader("Content-Type");
        log.error("统一异常处理 uri: {} content-type: {} exception: {}", request.getRequestURI(), contentType, e.toString());
        if (e instanceof BindException) {
            BindException bindException = (BindException) e;
            return jsr303Valid(bindException);
        }

        if (e instanceof MethodArgumentNotValidException) {
            MethodArgumentNotValidException ex = (MethodArgumentNotValidException) e;
            return jsr303BodyValid(ex);
        }

        return RestBody.failure(700, "系统异常！");
    }


    /**
     * Jsr 303 valid rest.
     * jsr303 校验异常处理 处理 非{@link org.springframework.web.bind.annotation.RequestBody} 参数校验
     *
     * @param e the e
     * @return rest
     */
    private Rest jsr303Valid(BindException e) {
        List<ObjectError> allErrors = e.getAllErrors();
        ObjectError objectError = allErrors.get(0);
        return RestBody.failure(700, objectError.getDefaultMessage());
    }

    /**
     * Jsr 303 body valid rest.
     * jsr303 校验异常处理 处理 {@link org.springframework.web.bind.annotation.RequestBody} 参数校验
     *
     * @param e the e
     * @return rest
     */
    private Rest jsr303BodyValid(MethodArgumentNotValidException e) {
        List<ObjectError> allErrors = e.getBindingResult().getAllErrors();
        ObjectError objectError = allErrors.get(0);
        return RestBody.failure(700, objectError.getDefaultMessage());
    }

}
